package com.shenhaofeng.app.widget.banner;

import android.content.Context;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
import android.graphics.Color;
import android.support.annotation.ColorInt;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import com.shenhaofeng.app.R;
import com.trello.rxlifecycle.android.RxLifecycleAndroid;

import java.util.concurrent.TimeUnit;

import rx.Observable;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;


/**
 * 轮播横幅视图,这个View可以播放一些子View，用于展示一些推荐或者重要的项目
 * Created by Administrator on 2016/1/20.
 */
public class Banner extends FrameLayout implements ViewPager.OnPageChangeListener {


    public static final int TOP = 1;

    public static final int BOTTOM = 2;

    public static final int LEFT = 3;

    public static final int RIGHT = 4;

    public static final int TOP_LEFT = 5;

    public static final int TOP_RIGHT = 6;

    public static final int BOTTOM_LEFT = 7;

    public static final int BOTTOM_RIGHT = 8;


    private PagerAdapter bannerAdapter;

    //    private List<View> childViews = new ArrayList<>();
    private ViewPager viewPager;

    private BannerIndicator indicator;

    private onPageListener pageListener;

    private DataSetObserver dataSetObserver = new DataSetObserver() {
        @Override
        public void onChanged() {
            pageListener.onPageCountChange(Banner.this);
        }
    };

    private int gravity = BOTTOM;

    private float ratio = 0.8f;

    private boolean autoScrollEnable = false;

    private long time;

    private TimeUnit timeUnit;

    private BannerScrollTimer mBannerScrollTimer;

    private boolean isAttachedToWindow = false;

    private Subscription mAutoScrollSubscription;


    public Banner(Context context) {
        this(context, null);
    }


    public Banner(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }


    public Banner(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    }


    private void init(Context context, AttributeSet attrs, int defStyleAttr) {
        mBannerScrollTimer = new BannerScrollTimer();
        mBannerScrollTimer.setup(this);
        viewPager = new ViewPager(getContext());
        viewPager.setAdapter(bannerAdapter);
        addView(viewPager);
        indicator = new BannerIndicator(getContext());
        setPageListener(indicator);
        LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        params.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
        indicator.setLayoutParams(params);
        addView(indicator);
        indicator.syncBanner(this);
        final TypedArray a = context.obtainStyledAttributes(
                attrs, R.styleable.Banner, defStyleAttr, 0);
        int standColor = a.getColor(R.styleable.Banner_standardColor, Color.GRAY);
        setStandardColor(standColor);
        int selectedColor = a.getColor(R.styleable.Banner_selectedColor, Color.BLACK);
        setSelectedColor(selectedColor);
        int size = a.getDimensionPixelSize(R.styleable.Banner_indicatorSize, 20);
        setIndicatorSize(size);
        int space = a.getDimensionPixelSize(R.styleable.Banner_indicatorSpace, 20);
        setIndicatorSpace(space);
        float ratio = a.getFloat(R.styleable.Banner_heightRatio, 0.8f);
        setRatio(ratio);
        int topPadding = a.getDimensionPixelSize(R.styleable.Banner_indicatorTopPadding, 20);
        int bottomPadding = a.getDimensionPixelSize(R.styleable.Banner_indicatorBottomPadding, 20);
        int leftPadding = a.getDimensionPixelSize(R.styleable.Banner_indicatorLeftPadding, 20);
        int rightPadding = a.getDimensionPixelSize(R.styleable.Banner_indicatorRightPadding, 20);
        setIndicatorPadding(topPadding, bottomPadding, leftPadding, rightPadding);
        int gravity = a.getInt(R.styleable.Banner_indicatorGravity, this.gravity);
        setIndicatorGravity(gravity);
    }


    public void setIndicatorDrawer(IndicatorDrawer indicatorDrawer) {
        indicator.setIndicatorDrawer(indicatorDrawer);
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        int widthSpec;
        int heightSpec;

        if (widthMode == MeasureSpec.EXACTLY) {
            widthSpec = widthMeasureSpec;
            heightSpec = MeasureSpec.makeMeasureSpec((int) (widthSize * ratio), MeasureSpec.EXACTLY);
        } else {
            widthSpec = widthMeasureSpec;
            heightSpec = heightMeasureSpec;
        }
        super.onMeasure(widthSpec, heightSpec);
    }


    public void setRatio(float ratio) {
        if (ratio <= 0) {
            ratio = 1;
        }
        this.ratio = ratio;
        requestLayout();
    }


    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                if (autoScrollEnable && mAutoScrollSubscription != null && !mAutoScrollSubscription.isUnsubscribed()) {
                    mAutoScrollSubscription.unsubscribe();
                }
                break;
            }
            case MotionEvent.ACTION_UP: {
                if (autoScrollEnable && mAutoScrollSubscription != null && !mAutoScrollSubscription.isUnsubscribed()) {
                    mAutoScrollSubscription.unsubscribe();
                }
                startAutoScroll();
                break;
            }
        }
        return super.dispatchTouchEvent(ev);
    }


    @Override
    protected void onAttachedToWindow() {
        isAttachedToWindow = true;
        super.onAttachedToWindow();
        viewPager.addOnPageChangeListener(this);
        if (autoScrollEnable) {
            startAutoScroll();
        }
    }


    @Override
    protected void onDetachedFromWindow() {
        isAttachedToWindow = false;
        super.onDetachedFromWindow();
        viewPager.removeOnPageChangeListener(this);
        if (mAutoScrollSubscription != null && !mAutoScrollSubscription.isUnsubscribed()) {
            mAutoScrollSubscription.unsubscribe();
        }
    }


    @Override
    public final void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }


    @Override
    public final void onPageSelected(int position) {
        indicator.syncBanner(this);
        if (pageListener != null) {
            pageListener.onPageSelected(position);
        }
    }


    @Override
    public final void onPageScrollStateChanged(int state) {

    }


    /**
     * 设置橱窗的适配器
     *
     * @param bannerAdapter
     */
    public void setBannerPagerAdapter(PagerAdapter bannerAdapter) {
        if (this.bannerAdapter != null) {
            this.bannerAdapter.unregisterDataSetObserver(dataSetObserver);
        }
        this.bannerAdapter = bannerAdapter;
        this.bannerAdapter.registerDataSetObserver(dataSetObserver);
//        this.bannerAdapter.setChildViewGroup(childViews);
        viewPager.setAdapter(this.bannerAdapter);
        indicator.syncBanner(this);
    }


    /**
     * 设置自动滚动能力
     */
    public void setAutoScroll(long time, TimeUnit timeUnit) {
        this.autoScrollEnable = true;
        this.time = time;
        this.timeUnit = timeUnit;
        if (isAttachedToWindow) {
            startAutoScroll();
        }
    }


    /**
     * 停止自动滚动
     */
    public void stopAutoScroll() {
        if (mAutoScrollSubscription != null && !mAutoScrollSubscription.isUnsubscribed()) {
            mAutoScrollSubscription.unsubscribe();
        }
        this.autoScrollEnable = false;
        this.time = 0;
        this.timeUnit = null;
    }


//    /**
//     * 设置childView
//     *
//     * @param childViewList
//     */
//    public void setChildView(List<View> childViewList) {
//        childViews.addAll(childViewList);
//        if (bannerAdapter != null) {
//            bannerAdapter.setChildViewGroup(childViews);
//            indicator.syncBanner(this);
//        }
//
//    }


    /**
     * 设置页码的监听
     *
     * @param pageListener
     */
    private void setPageListener(onPageListener pageListener) {
        this.pageListener = pageListener;
    }


    /**
     * 开始自动滚动
     */
    private void startAutoScroll() {
        mAutoScrollSubscription = Observable.interval(time, time, timeUnit)
                .compose(RxLifecycleAndroid.<Long>bindView(this))//在View从window上解绑时取消观察
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<Long>() {
                    @Override
                    public void call(Long aLong) {
                        mBannerScrollTimer.nextPage();
                    }
                }, new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {

                    }
                });
    }


    /**
     * 获取数据数量
     *
     * @return
     */
    public int getCount() {
        if (bannerAdapter == null) {
            return 0;
        }
        return bannerAdapter.getCount();
    }


    public int getCurrentItem() {
        return viewPager.getCurrentItem();
    }


    public void setCurrentItem(int page) {
        viewPager.setCurrentItem(page);
    }


    protected ViewPager getViewPager() {
        return viewPager;
    }


    public void setSelectedColor(@ColorInt int color) {
        indicator.setSelectedColor(color);
    }


    public void setStandardColor(@ColorInt int color) {
        indicator.setStandardColor(color);
    }


    public void setIndicatorSize(int size) {
        indicator.setIndicatorSize(size);
    }


    public void setIndicatorSpace(int space) {
        indicator.setIndicatorSpace(space);
    }


    public void setIndicatorPadding(int topPadding, int bottomPadding, int leftPadding, int rightPadding) {
        LayoutParams params = (LayoutParams) indicator.getLayoutParams();
        float density = getResources().getDisplayMetrics().density;
        params.bottomMargin = (int) (density * bottomPadding);
        params.topMargin = (int) (density * topPadding);
        params.leftMargin = (int) (density * leftPadding);
        params.rightMargin = (int) (density * rightPadding);
        indicator.postInvalidate();
    }


    public void setIndicatorGravity(int gravity) {
        if (gravity <= 0 && gravity >= 9) {
            return;
        }
        int g;
        switch (gravity) {
            case TOP: {
                g = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
                break;
            }
            case BOTTOM: {
                g = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
                break;
            }
            case LEFT: {
                g = Gravity.LEFT;
                break;
            }
            case RIGHT: {
                g = Gravity.RIGHT;
                break;
            }
            case TOP_LEFT: {
                g = Gravity.TOP | Gravity.LEFT;
                break;
            }
            case TOP_RIGHT: {
                g = Gravity.TOP | Gravity.RIGHT;
                break;
            }
            case BOTTOM_LEFT: {
                g = Gravity.BOTTOM | Gravity.LEFT;
                break;
            }
            case BOTTOM_RIGHT: {
                g = Gravity.BOTTOM | Gravity.RIGHT;
                break;
            }
            default:
                g = this.gravity;
                break;
        }
        LayoutParams params = (LayoutParams) indicator.getLayoutParams();
        params.gravity = g;
        requestLayout();
    }


    public interface onPageListener {
        void onPageSelected(int position);


        void onPageCountChange(Banner banner);
    }

}
